#include <sstream>
#include <ObjectInspectorDirectorOsg.h>
#include <ObjectInspectorItem.h>
#include <SceneViewerFunctions.h>
#include <VisitorNodeToItem.h>
#include <OsgClassDataSource/ObjectOsg.h>
#include <OsgClassDataSource/CameraManipulatorOsg.h>
#include <QString>
#include <osg/CopyOp>
#include <SelectorManagerOsg.h>
#include <InteractionWithUIFunctions.h>
#include <FunctionsPluginOsg.h>
#include <EDesignerCore.h>
#include <ClassFactoryObjectOsg.h>
#include <OsgClassDataSource/GroupOsg.h>
#include <OsgClassDataSource/NodeOsg.h>
#include <NodeInfoContainer.h>
#include <SelectorManagerOsg.h>
#include <SceneViewer.h>
#include <SwitchCameraManipulator.h>
#include <QFileDialog>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <ObjectInspectorVisitorChangeBackgroundOsg.h>
std::string getUiTypeString(const std::string& _type_string)
{
    std::string _ui_type_string;
	int pos1 = _type_string.find(":");
	if (pos1 != std::string::npos)
	{
		_ui_type_string = _type_string.substr(pos1+2, _type_string.size()-1);
	}
	else
	{
		pos1 = _type_string.find(" ");
		_ui_type_string = _type_string.substr(pos1+1, _type_string.size()-1);
	}
	return _ui_type_string;
}
QString getGenerateObjectTypeName( QString class_name)
{
    QString new_str = class_name.remove(0,3);
    return new_str;

}

ObjectInspectorDirectorOsg::ObjectInspectorDirectorOsg()
{
    m_count = 0;
    QAction* actionReadOsgModelFile = new QAction(QIcon("resource/action_3D_model_file.png"), QString("Read Model File"),0);
    m_actionList.push_back(actionReadOsgModelFile);
    QObject::connect(actionReadOsgModelFile, SIGNAL(triggered()), this, SLOT(actionReadOsgModelFile()));

    QAction* actionSaveToModelFile = new QAction(QIcon("resource/action_3D_model_file.png"), QString("Save to Model File"),0);
    m_actionList.push_back(actionSaveToModelFile);
    QObject::connect(actionSaveToModelFile, SIGNAL(triggered()), this, SLOT(actionWriteToOsgModelFile()));
    m_currentItem = NULL;
}

ObjectInspectorDirectorOsg::~ObjectInspectorDirectorOsg()
{

}

void ObjectInspectorDirectorOsg::rebuild(QStandardItem *model_root_item)
{
    //EngineFunctions::enginePause();
    //InteractionWithUIFunctions::sleep(3);
    EDesignerCore::instance()->simulationWaitUpdateEndAndStopSim();


    SelectorManagerOsg::instance()->cancelSelectedNode();


    //clear itemptr in sceneViewer, modelRoot
    SceneViewer::instance()->setUserDataContainer(NULL);
    SceneViewer::instance()->getModelRoot()->setUserDataContainer(NULL);

    //node tree
    VisitorNodeToItem visitor;
    visitor.setRootItem(model_root_item);   
    //SceneViewerFunctions::getSceneViewerModelRootNode()->accept(visitor);
    SceneViewer::instance()->accept(visitor);

    refreshItemColor();

    EDesignerCore::instance()->simulationstopWaitUpdateEnd();

}

bool ObjectInspectorDirectorOsg::addItemDown(EObject *parentObj, EObject *newObj)
{
    SelectorManagerOsg::instance()->cancelSelectedNode();
/*
    GroupOsg* parentGroupPtr = dynamic_cast<GroupOsg*>(parentObj);
    if(parentGroupPtr == NULL)return false;

    NodeOsg* newNodeObj = dynamic_cast<NodeOsg*>(newObj);
    if(newNodeObj == NULL)return false;

    osg::Group* osgGroupPtr = dynamic_cast<osg::Group*>(parentGroupPtr->getObject().get());
    if(osgGroupPtr == NULL)return false;


    osg::Node* osgNodePtr = dynamic_cast<osg::Node*>(newNodeObj->getObject().get());
    if(osgNodePtr == NULL)return false;

    if(osgGroupPtr->getName() == "SceneViewerRootNode" &&
            osgNodePtr->getName() != "SceneViewModelRoot") return false;


    return osgGroupPtr->addChild(osgNodePtr);
*/
    bool boolValue = false;
    ObjectOsg* parentObjOsg = dynamic_cast<ObjectOsg*>(parentObj);
    ObjectOsg* newObjOsg = dynamic_cast<ObjectOsg*>(newObj);

    if(parentObjOsg != NULL && newObjOsg != NULL)
    {
        osg::Group* parentGroup = dynamic_cast<osg::Group*>(parentObjOsg->getObject().get());
        osg::Node* newNode = dynamic_cast<osg::Node*>(newObjOsg->getObject().get());
        osgGA::CameraManipulator* cameraMani = dynamic_cast<osgGA::CameraManipulator*>(newObjOsg->getObject().get());
        if(parentGroup != NULL && newNode != NULL )
        {
            if(parentGroup->getName() == "SceneViewerRootNode" && newNode->getName() == "SceneViewModelRoot")
            {
                boolValue = true;
            }
            else if(parentGroup->getName() != "SceneViewerRootNode" && newNode->getName() == "SceneViewModelRoot")
            {
                boolValue = false;
            }
            else if(parentGroup->getName() == "SceneViewerRootNode" && newNode->getName() != "SceneViewModelRoot")
            {
                boolValue = false;
            }
            else if(parentGroup->getName() != "SceneViewerRootNode" && newNode->getName() != "SceneViewModelRoot")
            {
                boolValue = parentGroup->addChild(newNode);
            }
        }
        else if(parentGroup != NULL && parentGroup->getName() == "SceneViewerRootNode" && cameraMani != NULL)
        {
            boolValue = SceneViewer::instance()->getSwitchCameraManipulator()->addCameraManipulator(cameraMani);
            //if modelRoot has item
            NodeInfoContainer* modelRootInfoContainer = dynamic_cast<NodeInfoContainer*>(SceneViewer::instance()->getModelRoot()->getUserDataContainer());
            if(modelRootInfoContainer != NULL)
            {
                int modelRootRowIndex = modelRootInfoContainer->getObjectInspectorItem()->row();
                NodeInfoContainer* SceneViewerInfoContainer = dynamic_cast<NodeInfoContainer*>(SceneViewer::instance()->getUserDataContainer());
                if(SceneViewerInfoContainer != NULL)SceneViewerInfoContainer->getObjectInspectorItem()->insertRow(modelRootRowIndex, newObj->getObjItem());
            }
        }
    }
    return boolValue;
}

bool ObjectInspectorDirectorOsg::deleteItem(EObject *obj)
{
    SelectorManagerOsg::instance()->cancelSelectedNode();


    NodeOsg* nodeObj = dynamic_cast<NodeOsg*>(obj);
    CameraManipulatorOsg* cameraManiOsg = dynamic_cast<CameraManipulatorOsg*>(obj);
    if(nodeObj != NULL)
    {
        osg::Node* osgNodePtr = dynamic_cast<osg::Node*>(nodeObj->getObject().get());
        if(osgNodePtr != NULL)
        {
            if(osgNodePtr->getName() == "SceneViewModelRoot") return false;
            if(osgNodePtr->getName() == "SceneViewerRootNode") return false;
            if(osgNodePtr->getParent(0) != NULL)
                osgNodePtr->getParent(0)->removeChild(osgNodePtr);
            osg::Group* osgGroupPtr = dynamic_cast<osg::Group*>(osgNodePtr);
            if(osgGroupPtr != NULL)
            {
                osgGroupPtr->removeChildren(0, osgGroupPtr->getNumChildren() );
            }
            return true;
        }

    }
    else if(cameraManiOsg != NULL)
    {
        osgGA::CameraManipulator* cameraMani = dynamic_cast<osgGA::CameraManipulator*>(cameraManiOsg->getObject().get());
        if(cameraMani != NULL)
        {
            return SceneViewer::instance()->getSwitchCameraManipulator()->removeCameraManipulator(cameraMani);
        }

    }
    return false;

}

bool ObjectInspectorDirectorOsg::changeItemParent(EObject *parentObj, EObject *childObj)
{
    SelectorManagerOsg::instance()->cancelSelectedNode();

    GroupOsg* parentGroupPtr = dynamic_cast<GroupOsg*>(parentObj);
    if(parentGroupPtr == NULL)return false;

    NodeOsg* childNodeObj = dynamic_cast<NodeOsg*>(childObj);
    if(childNodeObj == NULL)return false;

    osg::Group* osgGroupPtr = dynamic_cast<osg::Group*>(parentGroupPtr->getObject().get());
    if(osgGroupPtr == NULL)return false;
    if(osgGroupPtr->getName() == "SceneViewerRootNode") return false;

    osg::Node* osgNodePtr = dynamic_cast<osg::Node*>(childNodeObj->getObject().get());
    if(osgNodePtr == NULL)return false;

    if(osgNodePtr->getName() == "SceneViewModelRoot") return false;
    if(osgNodePtr->getName() == "SceneViewerRootNode") return false;

    osgGroupPtr->addChild(osgNodePtr);
    osgNodePtr->getParent(0)->removeChild(osgNodePtr);
    return true;
}

bool ObjectInspectorDirectorOsg::copyItem(EObject *objPtr)
{
    SelectorManagerOsg::instance()->cancelSelectedNode();

    NodeOsg* osgObjPtr = dynamic_cast<NodeOsg*>(objPtr);
    if(osgObjPtr != NULL)
    {

        if(osgObjPtr->getObject()->getName() == "SceneViewModelRoot") return false;
        if(osgObjPtr->getObject()->getName() == "SceneViewerRootNode") return false;

        refresh();
        return true;
    }
    return false;
}

void ObjectInspectorDirectorOsg::refresh()
{
    SelectorManagerOsg::instance()->cancelSelectedNode();

    osg::ref_ptr<osg::Node> modelRoot = SceneViewerFunctions::getSceneViewerModelRootNode();
    //NodeInfoContainer* infoContainer = dynamic_cast<NodeInfoContainer*>(modelRoot->getUserDataContainer());
    //if(infoContainer == NULL) return;
    //QStandardItem* rootItem = infoContainer->getObjectInspectorItem()->parent();
    VisitorNodeToItem visitor;
    visitor.setRootItem(EDesignerCore::instance()->getRootItemPtr());

    modelRoot->accept(visitor);

    refreshItemColor();
}

void ObjectInspectorDirectorOsg::selectionItemChanged(QList<ObjectInspectorItem *> item_list)
{
    EDesignerCore::instance()->simulationWaitUpdateEndAndStopSim();

    //std::cout<<"selected item size = "<<item_list.size()<<std::endl;
    SelectorManagerOsg::instance()->cancelSelectedNode();
    for(int i = 0; i < item_list.size(); i++)
    {
        //selectItem(item_list.at(i));
        ObjectInspectorItem* itemPtr = item_list.at(i);
        NodeOsg* nodeOsg = dynamic_cast<NodeOsg*>(itemPtr->getObjectPtr().data());
        if(nodeOsg != NULL)
        {
            osg::Node* node = dynamic_cast<osg::Node*>(nodeOsg->getObject().get());
            if(node != NULL)
            {
                if(node->getName() == "SceneViewModelRoot" || node->getName() == "SceneViewerRootNode")
                {

                }
                else
                {
                    SelectorManagerOsg::instance()->addSelectedNode(node);
                }
               }
        }
    }

    //EngineFunctions::engineReStart();
    EDesignerCore::instance()->simulationstopWaitUpdateEnd();

}

QList<QAction *> ObjectInspectorDirectorOsg::getActionList()
{
    return m_actionList;
}

void ObjectInspectorDirectorOsg::currentItemChanged(ObjectInspectorItem *item_ptr)
{
    m_currentItem = item_ptr;
}

void ObjectInspectorDirectorOsg::refreshItemColor()
{
    ObjectInspectorVisitorChangeBackgroundOsg visitor;
    NodeInfoContainer* nodeInfoContainer = dynamic_cast<NodeInfoContainer* >(SceneViewer::instance()->getUserDataContainer());
    if(nodeInfoContainer != NULL)
    {
        ObjectInspectorItem* sceneViewerItem = nodeInfoContainer->getObjectInspectorItem();
        visitor.traverse( sceneViewerItem );
    }
}

void ObjectInspectorDirectorOsg::actionReadOsgModelFile()
{
    //std::cout<<"ObjectInspectorDirectorOsg::actionReadOsgModelFile"<<std::endl;
    if(m_currentItem != NULL)
    {
        //if current is a osg group
        GroupOsg* groupOsg = dynamic_cast<GroupOsg*>(m_currentItem->getObjectPtr().data());
        osg::Group* group = dynamic_cast<osg::Group*>(groupOsg->getObject().get());
        if(groupOsg != NULL && group != NULL && groupOsg->getObject()->getName() != "SceneViewerRootNode")
        {
            //show a file select dialog
            QString file_name = QFileDialog::getOpenFileName(0, "Read Osg Model File","","*.*");
            if(file_name.size() != 0)
            {
                osg::ref_ptr<osg::Node> readedNode = osgDB::readNodeFile(file_name.toStdString());
                osg::ref_ptr<osg::MatrixTransform> newMT = new osg::MatrixTransform;
                group->addChild(newMT);
                newMT->addChild(readedNode);

                refresh();
            }
        }
    }
}

void ObjectInspectorDirectorOsg::actionWriteToOsgModelFile()
{
    if(m_currentItem != NULL)
    {
        //if current is a osg group
        GroupOsg* groupOsg = dynamic_cast<GroupOsg*>(m_currentItem->getObjectPtr().data());
        osg::Group* group = dynamic_cast<osg::Group*>(groupOsg->getObject().get());
        if(groupOsg != NULL && group != NULL && groupOsg->getObject()->getName() != "SceneViewerRootNode")
        {
            //show a file select dialog
            QString file_name = QFileDialog::getSaveFileName(0, "Write to Osg Model File","","*.*");
            if(file_name.size() != 0)
            {
                osg::ref_ptr<osg::MatrixTransform> newMT = new osg::MatrixTransform;
                for(int i = 0; i < group->getNumChildren(); i++)
                {
                    newMT->addChild(group->getChild(i));
                }
                osg::Matrix m;
                m.makeRotate(-1.57, 1,0,0);
                //newMT->setMatrix(m);

                osgDB::writeNodeFile(*newMT, std::string(file_name.toLocal8Bit().data()));
                //osgDB::writeNodeFile(*group, std::string(file_name.toLocal8Bit().data()));
            }
        }
    }
}
